﻿using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.DatabaseServices.Filters;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Windows;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.ConstrainedExecution;
using System.Runtime.ExceptionServices;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Schema;
using static Autodesk.AutoCAD.Windows.SaveFileDialog;

namespace CADDemo0301
{
    public class Class1
    {
        [CommandMethod("GetLine")]
        public void GetLine()
        {
            Entity entity = GetEntity();
            if (entity is Line)
            {
                Line line = entity as Line;
                double lenght = line.Length;
                double angle = line.Angle;
                Vector3d delta = line.Delta;
                Vector3d normal = line.Normal;
                double thickness = line.Thickness;
                Point3d startPoint = line.StartPoint;
                Point3d endPoint = line.EndPoint;
            }
            Database db = HostApplicationServices.WorkingDatabase;
            using (Transaction trans = db.TransactionManager.StartTransaction())
            {
                LayerTable lt = (LayerTable)db.LayerTableId.GetObject(OpenMode.ForRead);
                foreach (ObjectId item in lt)
                {
                    //LayerTableRecord ltr=(LayerTableRecord)
                }
            }

        }

        [CommandMethod("AddCircle")]
        public void AddCircle()
        {

            Point3d center = new Point3d(10, 10, 0);
            Vector3d normal = Vector3d.ZAxis;
            double radius = 10;
            Circle circle = new Circle(center, normal, radius);
            AddEntity(circle);
        }
        [CommandMethod("AddArc")]
        public void AddArc()
        {
            Point3d center = Point3d.Origin;
            Vector3d normal = -Vector3d.ZAxis;
            double radius = 5;
            double startAngle = 0;
            double endAngle = Math.PI / 3;
            Arc arc = new Arc(center, normal, radius, startAngle, endAngle);
            AddEntity(arc);
        }
        [CommandMethod("AddEllipse")]
        public void AddEllipse()
        {
            Point3d center = new Point3d(0, 0, 0);
            Vector3d unitNormal = Vector3d.ZAxis;
            Vector3d majorAxis = new Vector3d(10, 10, 0);
            double radiusRatio = 0.5;
            double startAngle = Math.PI / 4;
            double endAngle = Math.PI;
            Ellipse ellipse = new Ellipse(center, unitNormal, majorAxis, radiusRatio, startAngle, endAngle);
            AddEntity(ellipse);
        }
        [CommandMethod("AddPolyline")]
        public void AddPolyline()
        {
            Polyline polyline = new Polyline();
            polyline.AddVertexAt(0, new Point2d(0, 0), 0, 0, 0);
            polyline.AddVertexAt(1, new Point2d(10, 0), 0, 0, 0);
            polyline.AddVertexAt(2, new Point2d(5, 5), 0, 0, 0);
            polyline.SetPointAt(1, new Point2d(15, 0));
            polyline.Reset(true, 1);
            AddEntity(polyline);
            //Polyline2d polyline2D = polyline.ConvertTo(false);
            //AddEntity(polyline2D);
            //Polyline polyline = GetEntity() as Polyline;
            //double bulge = polyline.GetBulgeAt(0);
            //;
            //List<Point3d> points = new List<Point3d>();
            //for (int i = 0; i < polyline.NumberOfVertices; i++)
            //{
            //    Point3d point3D = polyline.GetPoint3dAt(i);
            //    points.Add(point3D);
            //}
            //int index = 1;
            //SegmentType segmentType = polyline.GetSegmentType(index);
            //int index = 1;
            //LineSegment2d lineSegment2D = polyline.GetLineSegment2dAt(index);
            //int index = 1;
            //CircularArc2d circularArc2D = polyline.GetArcSegment2dAt(index);
            //Point3d pt3d = polyline.GetPointAtDist(5);
            //Point2d pt2d = new Point2d(8, 2);
            //double vaule = 60;
            //bool b = polyline.OnSegmentAt(1, pt2d, vaule);
        }
        [CommandMethod("AddMline")]
        public void AddMline()
        {
            Database database = HostApplicationServices.WorkingDatabase;
            string name = "STANDARD";
            ObjectId objectId = ObjectId.Null;
            using (Transaction trans = database.TransactionManager.StartTransaction())
            {
                DBDictionary ss = (DBDictionary)database.MLStyleDictionaryId.GetObject(OpenMode.ForRead);
                foreach (var item in ss)
                {
                    if (item.Key.ToUpper() == name)
                    {
                        objectId = item.Value;
                    }
                }
            }
            Mline mline = new Mline();

            mline.Style = objectId;
            mline.Normal = Vector3d.ZAxis;
            mline.Justification = MlineJustification.Zero;
            Point3d point3D1 = new Point3d(0, 0, 0);
            Point3d point3D2 = new Point3d(0, 10, 0);
            mline.AppendSegment(point3D1);
            mline.AppendSegment(point3D2);
            //mline.SupressStartCaps= true;
            //mline.SupressEndCaps= true;
            //Point3d lastVertex = new Point3d();
            //mline.RemoveLastSegment(lastVertex);
            //Point3d newPosition = new Point3d(10, 20, 0);
            //mline.MoveVertexAt(2, newPosition);
            //Point3d pt = new Point3d(0, 0, 0);
            //var po = mline.GetClosestPointTo(pt, true, true);
            Point3d pt = new Point3d(0, 5, 0);
            Vector3d vector3D = new Vector3d(-1, -1, 0);
            var po = mline.GetClosestPointTo(pt, vector3D, false, false);
            AddEntity(mline);
        }
        [CommandMethod("AddPolyline3d")]
        public void AddPolyline3d()
        {
            Poly3dType poly3DType = Poly3dType.SimplePoly;
            Point3dCollection point3DCollection = new Point3dCollection
            {
                new Point3d(0, 0, 0),
                new Point3d(10, 0, 0),
                new Point3d(10, 10, 0),
                //new Point3d(20, 10, 0),
            };
            bool isClosed = false;
            Polyline3d polyline3D = new Polyline3d(poly3DType, point3DCollection, isClosed);
            //Poly3dType poly3DType1 = Poly3dType.CubicSplinePoly;
            //polyline3D.ConvertToPolyType(poly3DType1);
            //polyline3D.PolyType = poly3DType1;
            //polyline3D.Straighten();
            //polyline3D.SplineFit(Poly3dType.QuadSplinePoly, 100);
            //int n = 0;
            //foreach (PolylineVertex3d item in polyline3D)
            //{
            //    if (n == 1)
            //    {
            //        PolylineVertex3d polylineVertex3D = new PolylineVertex3d(new Point3d(20, 10, 0));
            //        polyline3D.InsertVertexAt(item, polylineVertex3D);
            //        break;
            //    }
            //    n++;
            //}
            AddEntity(polyline3D);
            Database db = HostApplicationServices.WorkingDatabase;
            using (Transaction trans = db.TransactionManager.StartTransaction())
            {
                polyline3D = polyline3D.ObjectId.GetObject(OpenMode.ForWrite) as Polyline3d;
                int n = 0;
                foreach (ObjectId item in polyline3D)
                {
                    if (n == 0)
                    {
                        PolylineVertex3d polylineVertex3D = new PolylineVertex3d(new Point3d(5, -5, 0));
                        polyline3D.InsertVertexAt(item, polylineVertex3D);
                        break;
                    }
                    n++;
                }
                trans.Commit();
            }
            //PolylineVertex3d polylineVertex3D = new PolylineVertex3d(new Point3d(10, 10, 0));
            //Database db = HostApplicationServices.WorkingDatabase;
            //using (Transaction trans = db.TransactionManager.StartTransaction())
            //{
            //    polyline3D = polyline3D.ObjectId.GetObject(OpenMode.ForWrite) as Polyline3d;
            //    polyline3D.AppendVertex(polylineVertex3D);
            //    trans.Commit();
            //}

        }
        [CommandMethod("AddPolyline2d")]
        public void AddPolyline2d()
        {
            Point3dCollection pos = new Point3dCollection
            {
                new Point3d(0, 0, 0),
                new Point3d(10, 0, 0),
                new Point3d(10, 10, 0),
                new Point3d(20, 10, 0)
            };
            DoubleCollection doubles = new DoubleCollection
            {
                0,
                0,
                0,
                0
            };
            Polyline2d polyline2D = new Polyline2d(Poly2dType.SimplePoly, pos, 0, false, 0, 0, doubles);
            List<Point3d> point3Ds = new List<Point3d>();
            foreach (Vertex2d item in polyline2D)
            {
                Point3d point3D = polyline2D.VertexPosition(item);
                point3Ds.Add(point3D);
            }
            AddEntity(polyline2D);

        }
        [CommandMethod("AddDBText")]
        public void AddDBText()
        {
            DBText dBText = new DBText();
            dBText.TextString = "AaGg";
            //dBText.Justify = AttachmentPoint.BaseRight;
            //dBText.HorizontalMode = TextHorizontalMode.TextCenter;
            //dBText.IsMirroredInX = true;
            dBText.WidthFactor = 0.8;
            dBText.Height = 450;
            //dBText.Rotation = -Math.PI / 6;
            dBText.Oblique = Math.PI / 6;
            bool bbb = dBText.IsDefaultAlignment;
            AddEntity(dBText);
            //string name = dBText.TextString;
            //using (Transaction trans = HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction())
            //{
            //    DBObject dBObject = dBText.TextStyleId.GetObject(OpenMode.ForRead);
            //}
        }
        [CommandMethod("AddRotatedDimension")]
        public void AddRotatedDimension()
        {
            double rotation = 0;
            Point3d line1Point = new Point3d(0, 0, 0);
            Point3d line2Point = new Point3d(100, 0, 0);
            Point3d dimensionLinePoint = new Point3d(30, 40, 0);
            string dimensionText = "";
            Document doc = Application.DocumentManager.MdiActiveDocument;
            ObjectId dimensionStyle = doc.Database.DimStyleTableId;
            RotatedDimension rotatedDimension = new RotatedDimension(rotation, line1Point, line2Point, dimensionLinePoint, dimensionText, dimensionStyle);
            double o = rotatedDimension.Oblique;
            AddEntity(rotatedDimension);
        }
        [CommandMethod("AddAlignedDimension")]
        public void AddAlignedDimension()
        {
            Point3d line1Point = new Point3d(0, 0, 0);
            Point3d line2Point = new Point3d(100, 0, 0);
            Point3d dimensionLinePoint = new Point3d(50, 30, 0);
            string dimensionText = "";
            Document doc = Application.DocumentManager.MdiActiveDocument;
            ObjectId dimensionStyle = doc.Database.DimStyleTableId;
            AlignedDimension alignedDimension = new AlignedDimension(line1Point, line2Point, dimensionLinePoint, dimensionText, dimensionStyle);
            alignedDimension.Oblique = Math.PI / 3;
            AddEntity(alignedDimension);
        }
        [CommandMethod("AddLineAngularDimension2")]
        public void AddLineAngularDimension2()
        {
            Point3d line1Start = new Point3d(0, 0, 0);
            Point3d line1End = new Point3d(0, 50, 0);
            Point3d line2Start = new Point3d(10, 0, 0);
            Point3d line2End = new Point3d(50, 50, 0);
            Point3d arcPoint = new Point3d(30, 70, 0);
            string dimensionText = "";
            Document doc = Application.DocumentManager.MdiActiveDocument;
            ObjectId dimensionStyle = doc.Database.DimStyleTableId;
            LineAngularDimension2 lineAngularDimension2 = new LineAngularDimension2(line1Start,line1End,line2Start,line2End, arcPoint, dimensionText, dimensionStyle);
            AddEntity(lineAngularDimension2);
        }
        [CommandMethod("AddRadialDimension")]
        public void AddRadialDimension()
        {
            Point3d center = new Point3d(0, 0, 0);
            Point3d chordPoint = new Point3d(100, 0, 0);
            double leaderLength = 50;
            string dimensionText = "";
            Document doc = Application.DocumentManager.MdiActiveDocument;
            ObjectId dimensionStyle = doc.Database.DimStyleTableId;
            RadialDimension radialDimension = new RadialDimension(center, chordPoint, leaderLength, dimensionText, dimensionStyle);
            AddEntity(radialDimension);
        }
        [CommandMethod("AddDiametricDimension")]
        public void AddDiametricDimension()
        {
            Point3d chordPoint = new Point3d(50/Math.Sqrt(2), 50 / Math.Pow(2, 0.5), 0);
            Point3d farChordPoint = new Point3d(-50 / Math.Pow(2, 0.5), -50 / Math.Pow(2, 0.5), 0);
            double leaderLength = 20;
            string dimensionText = "";
            Document doc = Application.DocumentManager.MdiActiveDocument;
            ObjectId dimensionStyle = doc.Database.DimStyleTableId;
            DiametricDimension diametricDimension = new DiametricDimension(chordPoint, farChordPoint,leaderLength, dimensionText,dimensionStyle);
            AddEntity(diametricDimension);
        }
        [CommandMethod("AddArcDimension")]
        public void AddArcDimension()
        {
            Point3d centerPoint = new Point3d(0, 0, 0);
            Point3d xLine1Point = new Point3d(0, 50, 0);
            Point3d xLine2Point = new Point3d(50, 0, 0);
            Point3d arcPoint = new Point3d(70, 70, 0);
            string dimensionText = "";
            Document doc = Application.DocumentManager.MdiActiveDocument;
            ObjectId dimensionStyle = doc.Database.DimStyleTableId;
            ArcDimension arcDimension = new ArcDimension(centerPoint, xLine1Point, xLine2Point, arcPoint, dimensionText, dimensionStyle);
            arcDimension.ArcSymbolType = 1;
            arcDimension.HasLeader=true;
            AddEntity(arcDimension);
        }
        [CommandMethod("AddRadialDimensionLarge")]
        public void AddRadialDimensionLarge()
        {
            Point3d center = new Point3d(0, 0, 0);
            Point3d chordPoint = new Point3d(50, 60, 0);
            Point3d overrideCenter = new Point3d(0, 25, 0);
            Point3d jogPoint = new Point3d(25, 37, 0);
            double jogAngle = Math.PI / 2;
            string dimensionText = "";
            Document doc = Application.DocumentManager.MdiActiveDocument;
            ObjectId dimensionStyle = doc.Database.DimStyleTableId;
            RadialDimensionLarge radialDimensionLarge = new RadialDimensionLarge(center, chordPoint, overrideCenter, jogPoint, jogAngle, dimensionText, dimensionStyle);
            AddEntity(radialDimensionLarge);
        }
        [CommandMethod("AddOrdinateDimension")]
        public void AddOrdinateDimension()
        {
            bool useXAxis = true;
            Point3d definingPoint = new Point3d(50, 20, 0);
            Point3d leaderEndPoint = new Point3d(70, 50, 0);
            string dimensionText = "";
            Document doc = Application.DocumentManager.MdiActiveDocument;
            ObjectId dimensionStyle = doc.Database.DimStyleTableId;
            OrdinateDimension ordinateDimension = new OrdinateDimension(useXAxis, definingPoint, leaderEndPoint, dimensionText,dimensionStyle);
            ordinateDimension.Origin = new Point3d(50, 0, 0);
            AddEntity(ordinateDimension);
        }
        // 声明命令
        [CommandMethod("CreateBlock")]
        public void CreateBlock()
        {
            // 获取当前文档和数据库
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;

            // 获取编辑器对象
            Editor ed = doc.Editor;

            // 提示用户选择实体
            PromptSelectionResult psr = ed.GetSelection();

            // 如果用户成功选择了实体
            if (psr.Status == PromptStatus.OK)
            {
                // 获取选择集中的对象ID集合
                ObjectIdCollection ids = new ObjectIdCollection(psr.Value.GetObjectIds());

                // 启动事务处理
                using (Transaction tr = db.TransactionManager.StartTransaction())
                {
                    // 打开块表并获取当前空间记录ID
                    BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
                    ObjectId spaceId = db.CurrentSpaceId;

                    // 创建一个新的块表记录并命名为222
                    BlockTableRecord btr = new BlockTableRecord();
                    btr.Name = "222";

                    // 将新建的块表记录添加到块表中并升级打开权限以便修改
                    bt.UpgradeOpen();
                    bt.Add(btr);

                    // 通知事务处理器添加了新对象并降级打开权限以防止意外修改
                    tr.AddNewlyCreatedDBObject(btr, true);
                    bt.DowngradeOpen();

                    // 遍历选择集中的对象ID集合，将每个对象克隆到新建的块表记录中并删除原来的对象
                    foreach (ObjectId id in ids)
                    {
                        Entity ent = tr.GetObject(id, OpenMode.ForWrite) as Entity;
                        Entity cloneEnt = ent.Clone() as Entity;
                        btr.AppendEntity(cloneEnt);
                        tr.AddNewlyCreatedDBObject(cloneEnt, true);
                        ent.Erase();
                    }

                    // 提交事务处理并关闭事务处理器
                    tr.Commit();
                }

                ed.WriteMessage("\n已成功创建名为222的块。");
            }
        }
        // 声明命令
        [CommandMethod("InsertBlock")]
        public void InsertBlock()
        {
            // 获取当前文档和数据库
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;

            // 获取编辑器对象
            Editor ed = doc.Editor;

            // 提示用户输入插入点
            PromptPointResult ppr = ed.GetPoint("\n请输入插入点：");

            // 如果用户成功输入了插入点
            if (ppr.Status == PromptStatus.OK)
            {
                // 获取插入点坐标
                Point3d pt = ppr.Value;

                // 启动事务处理
                using (Transaction tr = db.TransactionManager.StartTransaction())
                {
                    // 打开块表并获取名为222的块表记录ID
                    BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
                    ObjectId btrId = bt["222"];

                    // 打开模型空间的块表记录并升级打开权限以便修改
                    BlockTableRecord ms = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;

                    // 创建一个新的块引用对象，指定其块表记录ID和插入点
                    BlockReference br = new BlockReference(pt, btrId);

                    // 将新建的块引用对象添加到模型空间的块表记录中并通知事务处理器
                    ms.AppendEntity(br);
                    tr.AddNewlyCreatedDBObject(br, true);

                    // 打开名为222的块表记录并遍历其中的实体，如果有属性定义，则创建对应的属性引用对象，并将其添加到新建的块引用对象中
                    BlockTableRecord btr = tr.GetObject(btrId, OpenMode.ForRead) as BlockTableRecord;

                    foreach (ObjectId id in btr)
                    {
                        Entity ent = tr.GetObject(id, OpenMode.ForRead) as Entity;

                        if (ent is AttributeDefinition ad)
                        {
                            AttributeReference ar = new AttributeReference();
                            ar.SetAttributeFromBlock(ad, br.BlockTransform);
                            ar.TextString = ad.TextString;  // 这里可以根据需要修改属性值

                            br.AttributeCollection.AppendAttribute(ar);
                            tr.AddNewlyCreatedDBObject(ar, true);
                        }
                    }

                    // 提交事务处理并关闭事务处理器
                    tr.Commit();
                }

                ed.WriteMessage("\n已成功在模型空间中插入名为222的块。");
            }
        }
        public Entity GetEntity()
        {
            Entity entity = null;
            Editor editor = Application.DocumentManager.MdiActiveDocument.Editor;
            PromptEntityResult per = editor.GetEntity("");
            if (per.Status == PromptStatus.OK)
            {
                Database db = HostApplicationServices.WorkingDatabase;
                using (Transaction trans = db.TransactionManager.StartTransaction())
                {
                    entity = (Entity)per.ObjectId.GetObject(OpenMode.ForRead);
                }
            }
            return entity;
        }
        private void AddEntity(Entity entity)
        {
            //开启事务
            Database db = HostApplicationServices.WorkingDatabase;
            using (Transaction trans = db.TransactionManager.StartTransaction())
            {
                //打开块表
                BlockTable bt = (BlockTable)trans.GetObject(db.BlockTableId, OpenMode.ForRead);
                //打开块表记录
                BlockTableRecord btr = (BlockTableRecord)trans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);

                btr.AppendEntity(entity);
                trans.AddNewlyCreatedDBObject(entity, true);


                trans.Commit();
            }
        }
    }
}
